#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

typedef long long DATA_TYPE;

typedef struct Link{
	struct Link *prev, *next;
}Link;

typedef struct DATA{
	DATA_TYPE data;
	Link coord;
}DATA;

// 传入 Link 指针，将其初始化
#define init_link(link) do{ \
	(link)->next = (link); \
	(link)->prev = (link); \
}while(0);


// 传入 Link 指针、用户结构体名、用户结构体中 Link 指针的成员名，获取对应用户结构体变量地址
#define get_node(link, type, member) \
	((type*)((char*)(link) - (uintptr_t)(&(((type*)0)->member))))
//	((type*)((uintptr_t)(&(link)) - (uintptr_t)(&(((type*)0)->member))))


// for循环 Link 链表，从 head->next 开始遍历除 head 以外结点，途中不可更改 head
#define for_node(link_type, head, variable) \
	for(link_type *variable = (head)->next; variable != (head); variable = variable->next)


// for循环 Link 链表，从 head->next 开始遍历除 head 以外结点，途中可更改 head
#define for_node_safe(link_type, head, variable, next_var) \
	for(link_type *variable = (head)->next, *next_var = variable->next; variable != (head); variable = next_var, next_var = next_var->next)


// 获取 Link 链表中的结点个数
#define get_node_num(link_type, head, num) do{\
	if(head == NULL) num = 0;\
	else { \
		num = 1; \
		for_node(link_type, head, variable) num++; \
}}while(0)


// 传入头 Link 结点、要插入的 Link 结点，将要插入的 Link 结点接到链表的尾部
#define add_node_tail(head, add) do{ \
	(head)->prev->next = (add); \
	(add)->prev = (head)->prev; \
	(head)->prev = (add); \
	(add)->next = (head); \
}while(0)


// 传入头 Link 结点、要插入的 Link 结点，将要插入的 Link 结点接到链表的头部
#define add_node_head(head, add) do{ \
	(head)->next->prev = (add); \
	(add)->next = (head)->next; \
	(head)->next = (add); \
	(add)->prev = (head); \
}while(0)


// 从链表中删除传入的 Link 结点
#define delete_node(node) do{\
	node->prev->next = node->next; \
	node->next->prev = node->prev; \
}while(0)


// 传入Link头结点，释放这一条链表的所有用户结构体
#define free_link(link_type, head, type, member) do{ \
	link_type *now = head; \
	while(now != NULL){ \
		type *h = get_node(now, type, member); \
		link_type *next = now->next; \
		now->prev->next = NULL; \
		printf("free %p\n", h); \
		free(h); \
		now = next; \
}}while(0)


DATA* createData(DATA_TYPE val){
	DATA *d = (DATA*)malloc(sizeof(DATA));
	d->data = val;
	init_link(&(d->coord));
	return d;
}

void freeData(DATA *head){
	free_link(Link, &(head->coord), DATA, coord);
}

DATA* getData(Link *l){
	DATA *d = get_node(l, DATA, coord);
	return d;
}

void insDataHead(DATA *head, DATA_TYPE val){
	DATA *add = createData(val);
	add_node_head(&(head->coord), &(add->coord));
}

void insDataTail(DATA *head, DATA_TYPE val){
	DATA *add = createData(val);
	add_node_tail(&(head->coord), &(add->coord));
}

void delData(DATA *head, DATA_TYPE val){
	Link *l = &(head->coord);
	for_node_safe(Link, l, r, n){
		DATA *d = getData(r);
		if(d->data == val){
			printf("找到 data == %lld 的结点，正在删除并释放该结点\n", val);
			delete_node(r);
			free(d);
			return;
		}
	}
	printf("没有找到 data == %lld 的结点\n", val);
}

void printAllData(DATA *head){
	Link *l = &(head->coord);
	printf("\n\t%lld ", head->data);
	for_node(Link, l, r){
		printf("%lld ", getData(r)->data);
	}
	printf("\n");
}

void debugData(Link *l){
	DATA *d = getData(l);
	printf("\n      该 Link 地址为：%p\n", l);
	printf("该结点的 DATA 地址为：%p\n\t\t值为：%lld\n", d, d->data);
	
	printf("  前驱的 Link 地址为：%p\n", d->coord.prev);
	DATA *p = getData(d->coord.prev);
	printf("      其 DATA 地址为：%p\n\t\t值为：%lld\n", p, p->data);
	
	printf("  后驱的 Link 地址为：%p\n", d->coord.next);
	DATA *n = getData(d->coord.next);
	printf("      其 DATA 地址为：%p\n\t\t值为：%lld\n\n", n, n->data);
}


int main(){
	DATA *d = createData(1);
	Link *head = &(d->coord);
	int num = 0;
	
	debugData(head);
	
	insDataHead(d, 2);
	insDataHead(d, 3);
	insDataTail(d, 4);
	
	get_node_num(Link, head, num);
	printf("\t%d\n", num);
	printAllData(d);
	
	printf("\n");
	debugData(head);
	
	delData(d, 2);
	get_node_num(Link, head, num);
	printf("\t%d\n", num);
	printAllData(d);
	
	debugData(head);
	freeData(d);
}
